package io.github.generator.loader;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.stream.StreamUtil;
import io.github.common.util.StringUtils;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.resource.Resource;
import org.apache.velocity.runtime.resource.loader.ResourceLoader;
import org.apache.velocity.util.ClassUtils;
import org.apache.velocity.util.ExtProperties;
import org.springframework.core.io.DefaultResourceLoader;

import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.*;

/**
 * 使用spring统一资源加载器
 *
 * @author haijun
 * @version 1.0.0
 * @email "mailto:haijun@qq.com"
 * @date 2024.11.09 12:47
 * @since 1.0.0
 */
public class SpringResourceLoaderEngine extends ResourceLoader {

    /**
     * Resource loader
     */
    private org.springframework.core.io.ResourceLoader resourceLoader;

    /**
     * Template paths
     */
    private final Map<String, String> templatePaths = Collections.synchronizedMap(new HashMap<>());

    /**
     * Paths
     */
    private final List<String> paths = new ArrayList<>();

    /**
     * Init
     *
     * @param configuration configuration
     * @since 1.0.0
     */
    @Override
    public void init(ExtProperties configuration) {
        if (configuration != null) {
            String className = StringUtils.trim(configuration.getString("spring.class"));
            if (StringUtils.isNotBlank(className)) {
                try {
                    this.resourceLoader = (org.springframework.core.io.ResourceLoader) ClassUtils.getNewInstance(className);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
            //noinspection unchecked
            Vector<String> vector = (Vector<String>) configuration.getVector(RuntimeConstants.RESOURCE_LOADER_PATHS);
            paths.addAll(vector);
            for (ListIterator<String> it = paths.listIterator(); it.hasNext(); ) {
                String path = org.apache.commons.lang3.StringUtils.trim(it.next());
                it.set(path);
            }
        }
        if (this.resourceLoader == null) {
            this.resourceLoader = new DefaultResourceLoader();
        }
    }

    /**
     * Gets resource reader *
     *
     * @param source   source
     * @param encoding encoding
     * @return the resource reader
     * @throws ResourceNotFoundException resource not found exception
     * @since 1.0.0
     */
    @Override
    public Reader getResourceReader(String source, String encoding) throws ResourceNotFoundException {
        Assert.notBlank(source, "模板名称不能为空");
        org.springframework.core.io.Resource resource = this.resourceLoader.getResource(source);
        if (resource.exists()) {
            Reader reader = null;
            File file = null;
            try {
                file = resource.getFile();
                reader = FileUtil.getUtf8Reader(file);
            } catch (IOException e) {
                log.error("获取模板文件失败", e);
            }
            if (reader != null) {
                templatePaths.put(source, file.getPath());
                return reader;
            }
        }
        throw new ResourceNotFoundException(source);
    }

    /**
     * 判断模板文件是否被修改了
     *
     * @param resource resource
     * @return the boolean
     * @since 1.0.0
     */
    @Override
    public boolean isSourceModified(Resource resource) {
        boolean modified = true;
        String fileName = resource.getName();
        String path = templatePaths.get(fileName);
        File currentFile = null;
        for (int i = 0; currentFile == null && i < paths.size(); i++) {
            String testPath = (String) paths.get(i);
            File testFile = getFile(testPath, fileName);
            if (testFile.canRead()) {
                currentFile = testFile;
            }
        }
        File file = getFile(path, fileName);
        if (currentFile == null || !file.exists()) {
        } else if (currentFile.equals(file) && file.canRead()) {
            modified = (file.lastModified() != resource.getLastModified());
        }
        return modified;
    }

    /**
     * Gets file *
     *
     * @param path     path
     * @param template template
     * @return the file
     * @since 1.0.0
     */
    private File getFile(String path, String template) {
        File file = null;
        if ("".equals(path)) {
            file = new File(template);
        } else {
            if (template.startsWith("/")) {
                template = template.substring(1);
            }
            file = new File(path, template);
        }
        return file;
    }

    /**
     * 获取到模板的最后修改时间
     *
     * @param resource resource
     * @return the last modified
     * @since 1.0.0
     */
    @Override
    public long getLastModified(Resource resource) {
        String path = templatePaths.get(resource.getName());
        File file = getFile(path, resource.getName());
        return file.canRead() ? file.lastModified() : 0;
    }
}
